/*
 * Copyright (C) 2017 Spreadtrum Communications Inc.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "sprd_panel.h"
#include "sprd_dsi.h"
#include "dsi/mipi_dsi_api.h"
#include "sprd_dphy.h"
#include <i2c.h>

static uint8_t init_data[] = {
	0x29,0x00,0x00,0x02,0xB0,0x00,
	0x29,0x00,0x00,0x06,0xB6,0x30,0x6b,0x00,0x82,0x03,
	0x29,0x00,0x00,0x05,0xB7,0x51,0x00,0x00,0x00,
	0x29,0x00,0x00,0x08,0xB8,0x57,0x3d,0x19,0xbe,0x1e,0x0a,0x0a,
	0x29,0x00,0x00,0x08,0xB9,0x6f,0x3d,0x28,0xbe,0x3c,0x14,0x0a,
	0x29,0x00,0x00,0x08,0xBA,0xb5,0x33,0x41,0xbe,0x64,0x23,0x0a,
	0x29,0x00,0x00,0x0C,0xBB,0x44,0x26,0xc3,0x1f,0x19,0x06,0x03,0xc0,0x00,0x00,0x10,
	0x29,0x00,0x00,0x0C,0xBC,0x32,0x4c,0xc3,0x52,0x32,0x1f,0x03,0xf2,0x00,0x00,0x13,
	0x29,0x00,0x00,0x0C,0xBD,0x24,0x68,0xc3,0xaa,0x3f,0x32,0x03,0xff,0x00,0x00,0x25,
	0x29,0x00,0x00,0x0D,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x0F,0xC0,0x00,0xcb,0x01,0x2c,0x0c,0x09,0x24,0x00,0x46,0x00,0x00,0x08,0x00,0x00,
	0x29,0x00,0x00,0x2A,0xC1,0x30,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x22,
	0x00,0x05,0x20,0x00,0x80,0xfa,0x40,0x00,0x80,0x0f,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x82,0xC2,0x00,0xa0,0xc0,0x02,0x02,0x00,0x09,0x05,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,
	0xc0,0x04,0x04,0x01,0x01,0xc1,0x00,0xa0,0x0a,0x00,
	0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x11,0x00,0xa0,
	0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x6D,0xC3,0x00,0x00,0xcb,0x01,0x93,0xb0,0x01,0x00,0x00,
	0x00,0x00,0x00,0xcb,0x01,0x00,0x09,0x9c,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0xaa,0xaa,0x00,0x00,0x00,0x00,
	0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
	0xc0,0x00,0x08,0x00,0xcb,0x00,0x00,0x01,0x00,0x00,
	0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x62,0xC4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x45,
	0x4c,0x51,0x4d,0x4d,0x61,0x5f,0x5d,0x0f,0x11,0x44,
	0x4f,0x4f,0xbe,0xbf,0x03,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x45,0x45,0x4c,0x51,0x4d,0x4d,0x61,0x5f,
	0x5d,0x0e,0x10,0x44,0x4f,0x4f,0xbe,0xbf,0x02,0xff,
	0xff,0xff,0xff,0xff,0xff,0x80,0xfe,0xe7,0x80,0xfe,
	0xe7,0x00,0x02,0x18,0x00,0x02,0x18,0x00,0xe0,0x00,
	0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
	0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x00,0x00,0x00,
	0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x06,0xC5,0x08,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x3F,0xC6,0x02,0x1a,0x08,0xfc,0xff,0xff,0xff,0x00,0x00,
	0x13,0x01,0xff,0x00,0x01,0x0c,0x3a,0x3a,0x3d,0x00,
	0x00,0x00,0x01,0x05,0x09,0x28,0x28,0x01,0x0c,0x3a,
	0x3a,0x3d,0x00,0x00,0x00,0x01,0x0b,0x00,0x00,0x00,
	0x1e,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,
	0x00,0x00,0x00,0x00,0x22,0x22,0x22,0x00,0x00,0x00,0x00,0x10,0x00,
	0x29,0x00,0x00,0x0F,0xCB,0xa0,0x80,0x70,0x00,0x20,0x00,0x00,0x2d,0x41,
	0x00,0x00,0x00,0x00,0xff,
	0x29,0x00,0x00,0x22,0xCE,0x5d,0x40,0x49,0x53,0x59,0x5e,0x63,0x68,0x6e,
	0x74,0x7e,0x8a,0x98,0xa8,0xbb,0xd0,0xe7,0xff,0x04,
	0x00,0x04,0x04,0x42,0x00,0x69,0x5a,0x40,0x40,0x00,
	0x00,0x04,0xfa,0x00,
	0x29,0x00,0x00,0x07,0xCF,0x00,0x00,0x80,0xa1,0x6a,0x00,
	0x29,0x00,0x00,0x13,0xD0,0xc7,0x14,0x8a,0x66,0x09,0x90,0x00,0xcc,0x0f,
	0x05,0xc7,0x14,0x12,0xfe,0x09,0x09,0xcc,0x00,
	0x29,0x00,0x00,0x1F,0xD1,0xd3,0xd3,0x1b,0xb0,0x07,0x07,0x3b,0x11,0xf1,
	0x11,0xf1,0x05,0x33,0x73,0x07,0x33,0x33,0x70,0xd3,
	0xd0,0x06,0x96,0x13,0x93,0x22,0x22,0x22,0xb3,0xbb,0x00,
	0x29,0x00,0x00,0x12,0xD2,0x00,0x00,0x00,0x02,0x7f,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x9A,0xD3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,
	0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,
	0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,
	0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,
	0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,
	0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,
	0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,
	0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,
	0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,
	0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,
	0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,
	0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,
	0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,
	0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,0xff,0xff,0xf7,
	0xff,0xff,0xf7,0xff,
	0x29,0x00,0x00,0x18,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x4B,0xD7,0x21,0x10,0x52,0x52,0x00,0xcb,0x00,0x46,0x00,
	0xb6,0x04,0xfd,0x01,0x00,0x03,0x00,0x05,0x05,0x05,
	0x07,0x04,0x05,0x06,0x07,0x00,0x02,0x02,0x08,0x03,
	0x03,0x08,0x04,0x08,0x08,0x0c,0x0b,0x0a,0x0a,0x0a,
	0x07,0x08,0x0a,0x06,0x00,0x08,0x00,0x00,0x00,0x00,
	0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x02,0x04,
	0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,
	0x06,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x3F,0xD8,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x05,0xDD,0x30,0x06,0x23,0x65,
	0x29,0x00,0x00,0x0B,0xDE,0x00,0x00,0x00,0x0f,0xff,0x00,0x00,0x00,0x00,0x10,
	0x29,0x00,0x00,0x05,0xE8,0x00,0x30,0x63,0x00,
	0x29,0x00,0x00,0x1E,0xEA,0x01,0x0e,0x02,0xc0,0x0a,0x40,0xa4,0x00,0x09,
	0x00,0x02,0xa6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x04,0xc2,0x00,0x11,0x00,0xcb,0x0c,0xb0,0x86,
	0x29,0x00,0x00,0x08,0xEB,0x00,0x00,0x00,0x00,0x01,0x00,0x11,
	0x29,0x00,0x00,0x0B,0xEC,0x05,0x50,0x00,0x10,0x44,0x0a,0x40,0xa4,0x02,0x3a,
	0x29,0x00,0x00,0x21,0xED,0x01,0x01,0x02,0x02,0x08,0x08,0x09,0x09,0x00,
	0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x12,0x02,
	0xc9,0x00,0x00,0x00,0x50,0x00,0x02,0xc9,0x00,0x00,0xa0,0x10,0x02,
	0x29,0x00,0x00,0x61,0xEE,0xc3,0x1f,0x00,0x00,0x00,0xfd,0x01,0x00,0x00,
	0x00,0x00,0xc2,0x5f,0x7f,0xf0,0x03,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0xc0,0x0f,0x7f,0x00,0x00,0x90,
	0xc9,0x09,0x09,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,
	0xc0,0x01,0x00,0x00,0x00,0x00,0xc0,0xc0,0x00,0x00,
	0x00,0x00,0x0f,0x01,0x00,0xc3,0x1f,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x67,0xEF,0x01,0x20,0x4c,0x08,0x60,0x00,0x00,0x00,0x00,
	0x32,0x32,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,
	0x4c,0x08,0x60,0x00,0x00,0x00,0x00,0x32,0x32,0x32,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,
	0x10,0x00,0x10,0x00,0x0a,0x0a,0x00,0x00,0x00,0x00,
	0x00,0x43,0x00,0x03,0x40,0x00,0x00,0x05,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x29,0x00,0x00,0x06,0xF9,0x44,0x3f,0x00,0x8d,0xbf,
	0x29,0x00,0x00,0x02,0xB0,0x03,
	0x29,0x00,0x00,0x02,0xB0,0x00,
	0x29,0x00,0x00,0x05,0xE5,0x03,0x07,0x00,0x00,
	0x29,0x00,0x00,0x4D,0xC7,0x00,0x00,0x00,0xD4,0x01,0x4B,0x01,0x6F,0x01,
	0x86,0x01,0x8F,0x01,0x93,0x01,0x90,0x01,0xAB,0x01,
	0x79,0x01,0xC8,0x01,0x87,0x01,0xC9,0x01,0x7F,0x01,
	0xE3,0x01,0xD2,0x02,0x3C,0x02,0x9C,0x02,0xAE,0x00,
	0x00,0x00,0xD4,0x01,0x4B,0x01,0x6F,0x01,0x86,0x01,
	0x8F,0x01,0x93,0x01,0x90,0x01,0xAB,0x01,0x79,0x01,
	0xC8,0x01,0x87,0x01,0xC9,0x01,0x7F,0x01,0xE3,0x01,
	0xD2,0x02,0x3C,0x02,0x9C,0x02,0xAE,
	0x29,0x00,0x00,0x02,0x51,0xFF,
	0x29,0x00,0x00,0x02,0x53,0x0C,
	0x29,0x00,0x00,0x02,0x55,0x00,
	0x29,0x00,0x00,0x02,0xB0,0x03,
	0x05,0x0a,0x00,0x01,0x29,
	0x05,0x64,0x00,0x01,0x11,
	CMD_END
};

static int mipi_dsi_send_cmds(struct sprd_dsi *dsi, void *data)
{
	uint16_t len;
	struct dsi_cmd_desc *cmds = data;

	if ((cmds == NULL) || (dsi == NULL))
		return -1;

	for (; cmds->data_type != CMD_END;) {
		len = (cmds->wc_h << 8) | cmds->wc_l;
		mipi_dsi_dcs_write(dsi, cmds->payload, len);
		if (cmds->wait)
			msleep(cmds->wait);
		cmds = (struct dsi_cmd_desc *)(cmds->payload + len);
	}
	return 0;
}

static int td4320_init(void)
{
	struct sprd_dsi *dsi = &dsi_device;
	struct sprd_dphy *dphy = &dphy_device;

	mipi_dsi_lp_cmd_enable(dsi, true);
	mipi_dsi_send_cmds(dsi, init_data);
	mipi_dsi_set_work_mode(dsi, SPRD_MIPI_MODE_VIDEO);
	mipi_dsi_state_reset(dsi);
	mipi_dphy_hs_clk_en(dphy, true);

	return 0;
}

static int td4320_readid(void)
{
	struct sprd_dsi *dsi = &dsi_device;
	uint8_t read_buf[5] = {0};

	mipi_dsi_lp_cmd_enable(dsi, true);
	mipi_dsi_set_max_return_size(dsi, 5);
	mipi_dsi_dcs_read(dsi, 0xbf, read_buf, 5);

	if((0x02 == read_buf[0]) && (0x3C == read_buf[1]) &&
	   ((0x50 == read_buf[2]) || (0x58 == read_buf[2])) && (0x0a == read_buf[3])) {
		pr_info("td4320 read id success!\n");
		return 0;
        }
	pr_err("td4320 read id failed:0x%x,0x%x,0x%x,0x%x\n",read_buf[0],read_buf[1],read_buf[2],read_buf[3]);

#ifdef CONFIG_GPOEXT3_MIPI_DSI_SWITCH_SEL
	aw9523_gpio_direction_output(AW9523_ADDR5B_GPIO_BASE + CONFIG_GPOEXT3_MIPI_DSI_SWITCH_SEL, 1);
#endif
	return -1;
}

static int td4320_power(int on)
{
	if (on) {
#ifdef CONFIG_FPGA_GPOEXT1_1V8EN
 				aw9523_gpio_request(AW9523_ADDR59_GPIO_BASE + CONFIG_FPGA_GPOEXT1_1V8EN);
 				aw9523_gpio_direction_output(AW9523_ADDR59_GPIO_BASE + CONFIG_FPGA_GPOEXT1_1V8EN, 1);
#endif

#ifdef CONFIG_GPOEXT3_MIPI_DSI_SWITCH_SEL
 				aw9523_gpio_direction_output(AW9523_ADDR5B_GPIO_BASE + CONFIG_GPOEXT3_MIPI_DSI_SWITCH_SEL, 0);
#endif
#ifdef CONFIG_LCM_GPOEXT0_AVDDEN
				aw9523_gpio_request(AW9523_ADDR5A_GPIO_BASE + CONFIG_LCM_GPOEXT0_AVDDEN);
				aw9523_gpio_direction_output(AW9523_ADDR5A_GPIO_BASE + CONFIG_LCM_GPOEXT0_AVDDEN, 1);
				mdelay(10);
#endif
#ifdef CONFIG_LCM_GPOEXT0_AVEEEN
				aw9523_gpio_request(AW9523_ADDR5A_GPIO_BASE + CONFIG_LCM_GPOEXT0_AVEEEN);
				aw9523_gpio_direction_output(AW9523_ADDR5A_GPIO_BASE + CONFIG_LCM_GPOEXT0_AVEEEN, 1);
				mdelay(20);
#endif

		sprd_gpio_request(NULL, CONFIG_LCM_GPIO_RSTN);
		sprd_gpio_direction_output(NULL, CONFIG_LCM_GPIO_RSTN, 1);
		mdelay(5);
		sprd_gpio_direction_output(NULL, CONFIG_LCM_GPIO_RSTN, 0);
		mdelay(5);
		sprd_gpio_direction_output(NULL, CONFIG_LCM_GPIO_RSTN, 1);
		mdelay(20);
	} else {
		sprd_gpio_direction_output(NULL, CONFIG_LCM_GPIO_RSTN, 0);
		mdelay(5);
	}

	return 0;
}

static struct panel_ops td4320_ops = {
	.init = td4320_init,
	.read_id = td4320_readid,
	.power = td4320_power,
};

static struct panel_info td4320_info = {
	/* common parameters */
	.lcd_name = "lcd_td4320_truly_mipi_fhd",
	.type = SPRD_PANEL_TYPE_MIPI,
	.bpp = 24,
//	.fps = 60,
	.width = 1080,
	.height = 2340,

	/* DPI specific parameters */
	.pixel_clk = 192000000, /*Hz*/
	.rgb_timing = {
		.hfp = 230,
		.hbp = 15,
		.hsync = 2,
		.vfp = 4,
		.vbp = 55,
		.vsync = 10,
	},

	/* MIPI DSI specific parameters */
#ifdef CONFIG_LCD_MIPI_CLOCK
	.phy_freq = CONFIG_LCD_MIPI_CLOCK,
#else
	.phy_freq = 1400000,
#endif
	.lane_num = 4,
	.work_mode = SPRD_MIPI_MODE_VIDEO,
	.burst_mode = VIDEO_BURST_WITH_SYNC_PULSES,
	.nc_clk_en = false,
};

struct panel_driver td4320_truly_driver = {
	.info = &td4320_info,
	.ops = &td4320_ops,
};
